package com.ifacebox.arcsoft.face;

import com.arcsoft.face.*;
import com.arcsoft.face.toolkit.ImageFactory;
import com.arcsoft.face.toolkit.ImageInfo;
import com.ifacebox.arcsoft.face.model.*;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author znn
 */
@RestController
public class ArcSoftFaceController {
    private static final Logger logger = LoggerFactory.getLogger(ArcSoftFaceController.class);
    @Resource
    private ArcSoftFaceConfigProperties faceConfigProperties;
    @Resource
    private GenericObjectPool<ArcSoftFaceEngine> faceEnginePool;

    @PostMapping("/face/compare")
    public FaceCompareResponse faceCompare(@RequestBody FaceCompareRequest request) {
        long ms = System.currentTimeMillis();
        FaceCompareResponse response = null;
        ArcSoftFaceEngine faceEngine = null;
        try {
            ImageInfo imageInfo1 = ImageFactory.getRGBData(ObjectUtils.isEmpty(request) ? null : request.getImage1());
            ImageInfo imageInfo2 = ImageFactory.getRGBData(ObjectUtils.isEmpty(request) ? null : request.getImage2());
            if (ObjectUtils.isEmpty(imageInfo1) || ObjectUtils.isEmpty(imageInfo2)) {
                return response = new FaceCompareResponse(FaceStatusResponse.INVALID_PARAMETERS);
            }
            faceEngine = faceEnginePool.borrowObject();
            //证件照
            List<FaceInfo> faceInfoList = faceEngine.faceDetection(imageInfo1);
            if (ObjectUtils.isEmpty(faceInfoList)) {
                return response = new FaceCompareResponse(FaceStatusResponse.NO_FACE);
            }
            FaceFeature faceFeature1 = faceEngine.faceFeature(imageInfo1, faceInfoList.get(0));
            //生活照
            faceInfoList = faceEngine.faceDetection(imageInfo2);
            if (ObjectUtils.isEmpty(faceInfoList)) {
                return response = new FaceCompareResponse(FaceStatusResponse.NO_FACE);
            }
            //生活照活体检测
            if (faceConfigProperties.isSupportLiveness() && !faceEngine.faceLiveness(imageInfo2, faceInfoList
                    , faceConfigProperties.getLivenessRgbThreshold(), faceConfigProperties.getLivenessIrThreshold())) {
                return response = new FaceCompareResponse(FaceStatusResponse.NO_LIVENESS);
            }
            FaceFeature faceFeature2 = faceEngine.faceFeature(imageInfo2, faceInfoList.get(0));
            //比对
            float faceScore = faceEngine.faceCompare(faceFeature1, faceFeature2);
            FaceCompare faceCompare = new FaceCompare();
            faceCompare.setScore(faceScore);
            faceCompare.setScoreLimit(faceConfigProperties.getFaceThreshold());
            faceCompare.setFace(new FacePosition[]{faceEngine.facePosition(faceInfoList.get(0).getRect())});
            return response = new FaceCompareResponse(FaceStatusResponse.SUCCESS, faceCompare);
        } catch (Exception e) {
            return response = new FaceCompareResponse(FaceStatusResponse.FAILURE, e.getMessage());
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("{}\t{}ms\t{}", faceEngine == null ? -1 : faceEngine.hashCode(), (System.currentTimeMillis() - ms), response);
            }
            if (faceEngine != null) {
                faceEnginePool.returnObject(faceEngine);
            }
        }
    }

    @PostMapping("/face/detection")
    @ResponseBody
    public FaceDetectionResponse faceDetection(@RequestBody FaceDetectionRequest request) {
        long ms = System.currentTimeMillis();
        FaceDetectionResponse response = null;
        ArcSoftFaceEngine faceEngine = null;
        try {
            ImageInfo imageInfo = ImageFactory.getRGBData(ObjectUtils.isEmpty(request) ? null : request.getImage());
            if (ObjectUtils.isEmpty(imageInfo)) {
                return response = new FaceDetectionResponse(FaceStatusResponse.INVALID_PARAMETERS);
            }
            faceEngine = faceEnginePool.borrowObject();
            List<FaceInfo> faceInfoList = faceEngine.faceDetection(imageInfo);
            if (ObjectUtils.isEmpty(faceInfoList)) {
                return response = new FaceDetectionResponse(FaceStatusResponse.NO_FACE);
            }
            //生活照活体检测
            if (faceConfigProperties.isSupportLiveness() && !faceEngine.faceLiveness(imageInfo, faceInfoList
                    , faceConfigProperties.getLivenessRgbThreshold(), faceConfigProperties.getLivenessIrThreshold())) {
                return response = new FaceDetectionResponse(FaceStatusResponse.NO_LIVENESS);
            }
            List<FacePosition> facePositionList = new ArrayList<>(faceInfoList.size());
            for (FaceInfo faceInfo : faceInfoList) {
                facePositionList.add(faceEngine.facePosition(faceInfo.getRect()));
            }
            FaceDetection faceDetection = new FaceDetection();
            faceDetection.setFace(facePositionList.toArray(new FacePosition[0]));
            return response = new FaceDetectionResponse(FaceStatusResponse.SUCCESS, faceDetection);
        } catch (Exception e) {
            return response = new FaceDetectionResponse(FaceStatusResponse.FAILURE, e.getMessage());
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("{}\t{}ms\t{}", faceEngine == null ? -1 : faceEngine.hashCode(), (System.currentTimeMillis() - ms), response);
            }
            if (faceEngine != null) {
                faceEnginePool.returnObject(faceEngine);
            }
        }
    }
}